package com.mxpio.erp.plan.controller;

import com.mxpio.erp.common.enums.OrderStatusEnums;
import com.mxpio.erp.common.jpa.model.Order;
import com.mxpio.erp.common.order.policy.OrderContext;
import com.mxpio.erp.common.order.service.OrderLineService;
import com.mxpio.erp.common.order.service.OrderService;
import com.mxpio.erp.common.plan.entity.OrganizationDemand;
import com.mxpio.erp.common.plan.entity.OrganizationDemandLine;
import com.mxpio.erp.common.plan.service.OrganizationDemandLineService;
import com.mxpio.erp.common.plan.service.OrganizationDemandService;
import com.mxpio.erp.common.vo.OrderExcuteVo;
import com.mxpio.erp.common.workshop.entity.ManufactureOrder;
import com.mxpio.erp.plan.policy.impl.DefaultODRecPolicy;
import com.mxpio.erp.plan.policy.impl.DefaultODRefillPolicy;
import com.mxpio.erp.plan.policy.impl.DefaultODRejectPolicy;
import com.mxpio.erp.plan.policy.impl.DefectiveRejPolicy;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.policy.CrudContext;
import com.mxpioframework.jpa.policy.impl.SmartCrudPolicyAdapter;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.Operator;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.util.List;

@Slf4j
@Tag(name = "OrganizationDemandController", description = "组织需求接口")
@RestController
@RequestMapping("/erp/plan/od/")
public class OrganizationDemandController {

	@Autowired
	private OrganizationDemandService organizationDemandService;
	@Autowired
	private OrganizationDemandLineService organizationDemandLineService;

	@Autowired
	private OrderService orderService;

	@Autowired
	private OrderLineService orderLineService;

	@GetMapping("list")
	@Operation(summary = "组织需求列表", description = "获取组织需求列表（无分页）", method = "GET")
	public Result<List<OrganizationDemand>> list(@Parameter(description = "查询参数") Criteria criteria)
			throws UnsupportedEncodingException {
		List<OrganizationDemand> organizationDemand = organizationDemandService.list(OrganizationDemand.class, criteria);
		return Result.OK(organizationDemand);
	}
	
	@GetMapping("page")
	@Operation(summary = "组织需求列表", description = "获取组织需求列表（分页）", method = "GET")
	public Result<Page<OrganizationDemand>> page(@Parameter(description = "查询参数") Criteria criteria,
			@Parameter(description = "每页条数") Integer pageSize, @Parameter(description = "页号") Integer pageNo)
			throws UnsupportedEncodingException {
		Pageable page = PageRequest.of(pageNo - 1, pageSize);
		Page<OrganizationDemand> organizationDemand = organizationDemandService.listPage(OrganizationDemand.class, page, criteria);
		return Result.OK(organizationDemand);
	}

	@GetMapping("list/{id}")
	@Operation(summary = "根据id获取组织需求", description = "根据id获取组织需求", method = "GET")
	public Result<OrganizationDemand> getById(
			@Parameter(description = "ID") @PathVariable(name = "id", required = true) String id) {
		OrganizationDemand organizationDemand = organizationDemandService.getById(OrganizationDemand.class, id);
		return Result.OK(organizationDemand);
	}

	@RequestMapping("save")
	@Operation(summary = "保存组织需求", description = "保存组织需求")
	@Transactional(readOnly = false)
	public Result<OrganizationDemand> save(@RequestBody OrganizationDemand organizationDemand) {
		organizationDemandService.save(organizationDemand,new SmartCrudPolicyAdapter(){
			@Override
			public boolean beforeInsert(CrudContext context) {
				Object o = context.getEntity();
				if(o instanceof OrganizationDemandLine){
					OrganizationDemand dbOrganizationDemand = context.getParent();
					((OrganizationDemandLine) o).setBizNo(dbOrganizationDemand.getBizNo());
				}
				return true;
			}
		});
		return Result.OK(organizationDemand);
	}

	@DeleteMapping("remove/{ids}")
	@Operation(summary = "根据ids删除组织需求", description = "删除组织需求", method = "DELETE")
	@Transactional(readOnly = false)
	public Result<OrganizationDemand> remove(
			@Parameter(description = "id，多个单号用英文逗号分隔") @PathVariable(name = "ids", required = true) String ids) {
		String[] id = ids.split(",");
		for (String key : id) {
			Criteria c = Criteria.create().addCriterion("bizNo", Operator.EQ, key);
			organizationDemandLineService.removeBatch(OrganizationDemandLine.class, c);
			organizationDemandService.delete(OrganizationDemand.class, key);
		}
		return Result.OK();
	}
	
	@PutMapping("submit/{id}")
    @Operation(summary = "提交组织需求", description = "提交组织需求", method = "PUT")
    public Result<OrganizationDemand> submit(@Parameter(description = "ID") @PathVariable(name = "id", required = true) String id) {
		OrganizationDemand organizationDemand = organizationDemandService.getById(OrganizationDemand.class, id);
        if (organizationDemand.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.CREATE.getStatusCode())) {
            return organizationDemandService.updateBpmnStatus(organizationDemand, OrderStatusEnums.BpmnStatus.AUDITING);
        } else {
            return Result.error("非开立状态不可提交");
        }
    }
	
	@PutMapping("audit/{id}")
    @Operation(summary = "审核组织需求", description = "审核组织需求", method = "PUT")
    public Result<OrganizationDemand> audit(@Parameter(description = "ID") @PathVariable(name = "id", required = true) String id) {
		OrganizationDemand organizationDemand = organizationDemandService.getById(OrganizationDemand.class, id);
        if (organizationDemand.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode())) {
            return organizationDemandService.updateBpmnStatus(organizationDemand,OrderStatusEnums.BpmnStatus.AUDITED);
        } else {
            return Result.error("非审核中状态不可审核");
        }
    }

    @PutMapping("abandon/{id}")
    @Operation(summary = "弃审组织需求", description = "弃审组织需求", method = "PUT")
    public Result<OrganizationDemand> abandon(@Parameter(description = "ID") @PathVariable(name = "id", required = true) String id) {
    	OrganizationDemand organizationDemand = organizationDemandService.getById(OrganizationDemand.class, id);
        if (organizationDemand.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITING.getStatusCode())
				|| organizationDemand.getBpmnStatus().equals(OrderStatusEnums.BpmnStatus.AUDITED.getStatusCode())) {
            return organizationDemandService.updateBpmnStatus(organizationDemand, OrderStatusEnums.BpmnStatus.CREATE);
        } else {
            return Result.error("非审核中、已审核状态不可审核");
        }
    }

	@RequestMapping("execute/receive/{bizNo}")
	@Operation(summary = "", description = "收料")
	public Result<Object> receiveExec(@PathVariable(name = "bizNo", required = true) String bizNo,
									  @RequestBody OrderExcuteVo orderExcuteVo) {
		OrganizationDemand organizationDemand = organizationDemandService.getById(OrganizationDemand.class, bizNo);
		if (organizationDemand.getCloseStatus().equals(OrderStatusEnums.CloseStatus.CLOSED.getStatusCode())){
			return Result.error("关闭状态不能执行该操作");
		}
		if (organizationDemand.getOrderStatus().equals(OrderStatusEnums.OrderStatus.FINISHED.getStatusCode())){
			return Result.error("已完成状态不能执行该操作");
		}
		if (organizationDemand.getOrderStatus().equals(OrderStatusEnums.OrderStatus.CLEARED.getStatusCode())){
			return Result.error("已结算状态不能执行该操作");
		}
		OrderContext context = orderService.execute(organizationDemand, new DefaultODRecPolicy(orderExcuteVo.getLines(),orderLineService));
		if(CollectionUtils.isEmpty(context.getErrors())) {
			return Result.OK();
		}else {
			return Result.error(context.getErrors().get(0));
		}
	}

	@RequestMapping("execute/reject/{bizNo}")
	@Operation(summary = "退货", description = "退料")
	public Result<Object> rejectExec(@PathVariable(name = "bizNo", required = true) String bizNo,
									 @RequestBody OrderExcuteVo orderExcuteVo) {
		OrganizationDemand organizationDemand = organizationDemandService.getById(OrganizationDemand.class, bizNo);
		if (organizationDemand.getCloseStatus().equals(OrderStatusEnums.CloseStatus.CLOSED.getStatusCode())){
			return Result.error("关闭状态不能执行该操作");
		}
		/*if (organizationDemand.getOrderStatus().equals(OrderStatusEnums.OrderStatus.FINISHED.getStatusCode())){
			return Result.error("已完成状态不能执行该操作");
		}*/
		if (organizationDemand.getOrderStatus().equals(OrderStatusEnums.OrderStatus.CLEARED.getStatusCode())){
			return Result.error("已结算状态不能执行该操作");
		}
		OrderContext context = orderService.execute(organizationDemand, new DefaultODRejectPolicy(orderExcuteVo.getLines(),orderLineService));
		if(CollectionUtils.isEmpty(context.getErrors())) {
			return Result.OK();
		}else {
			return Result.error(context.getErrors().get(0));
		}
	}

	@RequestMapping("execute/refill/{bizNo}")
	@Operation(summary = "", description = "补料")
	public Result<Object> refillExec(@PathVariable(name = "bizNo", required = true) String bizNo,
									  @RequestBody OrderExcuteVo orderExcuteVo) {
		OrganizationDemand organizationDemand = organizationDemandService.getById(OrganizationDemand.class, bizNo);
		if (organizationDemand.getCloseStatus().equals(OrderStatusEnums.CloseStatus.CLOSED.getStatusCode())){
			return Result.error("关闭状态不能执行该操作");
		}
		/*if (organizationDemand.getOrderStatus().equals(OrderStatusEnums.OrderStatus.FINISHED.getStatusCode())){
			return Result.error("已完成状态不能执行该操作");
		}*/
		if (organizationDemand.getOrderStatus().equals(OrderStatusEnums.OrderStatus.CLEARED.getStatusCode())){
			return Result.error("已结算状态不能执行该操作");
		}
		OrderContext context = orderService.execute(organizationDemand, new DefaultODRefillPolicy(orderExcuteVo.getLines(),orderLineService));
		if(CollectionUtils.isEmpty(context.getErrors())) {
			return Result.OK();
		}else {
			return Result.error(context.getErrors().get(0));
		}
	}


	@RequestMapping("excute_scrap/{bizNo}")
	@Operation(summary = "不良品退料", description = "不良品退料")
	public Result<Object> excuteScrap(@PathVariable(name = "bizNo", required = true) String bizNo,
									  @RequestBody OrderExcuteVo orderExcuteVo) {
		OrganizationDemand organizationDemand = organizationDemandService.getById(OrganizationDemand.class, bizNo);
		if (organizationDemand.getCloseStatus().equals(OrderStatusEnums.CloseStatus.CLOSED.getStatusCode())){
			return Result.error("关闭状态不能执行该操作");
		}
		/*if (organizationDemand.getOrderStatus().equals(OrderStatusEnums.OrderStatus.FINISHED.getStatusCode())){
			return Result.error("已完成状态不能执行该操作");
		}*/
		if (organizationDemand.getOrderStatus().equals(OrderStatusEnums.OrderStatus.CLEARED.getStatusCode())){
			return Result.error("已结算状态不能执行该操作");
		}
		OrderContext context = orderService.execute(organizationDemand, new DefectiveRejPolicy(orderExcuteVo.getLines(), orderLineService));
		if(CollectionUtils.isEmpty(context.getErrors())) {
			return Result.OK();
		}else {
			return Result.error(context.getErrors().get(0));
		}
	}

	@PutMapping("clear/{bizNo}")
	@Operation(summary = "结算组织需求", description = "结算组织需求", method = "PUT")
	public Result<? extends Order> clear(@Parameter(description="业务单号") @PathVariable(name = "bizNo", required = true) String bizNo) {
		return organizationDemandService.clear(bizNo);
	}

	@PutMapping("finish/{bizNo}")
	@Operation(summary = "强制完工", description = "强制完工", method = "PUT")
	public Result<? extends Order> finish(@Parameter(description="业务单号") @PathVariable(name = "bizNo", required = true) String bizNo) {
		OrganizationDemand order = organizationDemandService.getById(OrganizationDemand.class, bizNo);
		if(OrderStatusEnums.CloseStatus.CLOSED.getStatusCode().equals(order.getCloseStatus())){
			return Result.error("已关闭状态不可报完工");
		}
		if(OrderStatusEnums.OrderStatus.CLEARED.getStatusCode().equals(order.getOrderStatus())){
			return Result.error("已结清状态不可报完工");
		}
		if(OrderStatusEnums.OrderStatus.FINISHED.getStatusCode().equals(order.getOrderStatus())){
			return Result.error("已完成状态不可重复报完工");
		}
		return orderService.updateOrderStatus(order, OrderStatusEnums.OrderStatus.FINISHED);
	}
}
